/*
 * Spring 2012 TCSS360 Deliverable 3
 * Richard Nguyen
 */

package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;

import model.Auction;
import model.CalendarModel;
import model.Item;
import model.NPOStaffMember;
import model.User;
import model.UserAccess;
import storage.ProgramStateHandler;

@SuppressWarnings("serial")
public class AuctionGUI extends JPanel {

	private static final int FRAME_WIDTH = 600;

	private static final int FRAME_HEIGHT = 500;

	private static final String DATE_PATTERN = "MM/d/yyyy";

	private static final SimpleDateFormat DF =
			new SimpleDateFormat(DATE_PATTERN);

	private static final String TIME_PATTERN = "h:mm:ss a";

	private static final SimpleDateFormat TF =
			new SimpleDateFormat(TIME_PATTERN);

	private static final int SECONDS_PER_HOUR = 3600;

	private static final int UNIT_PER_MIN = 60;

	private static final int CMT_WIDTH = 300;

	private static final int CMT_HEIGHT = 150;

	private static final Font STD_FONT = new Font("Dialog",
			Font.PLAIN, 18);

	private static final JLabel NPO_NAME = new JLabel(
			"NPO Name: ");

	private static final JLabel DATE = new JLabel("Date: ");

	private static final JLabel START_TIME = new JLabel(
			"Start time: ");

	private static final JLabel END_TIME = new JLabel(
			"End time: ");

	private static final JLabel COMMENTS = new JLabel(
			"Comments: ");

	private final JFrame my_frame;
	private final JLabel NPO_name;
	private final JLabel date;
	private final JLabel start_time;
	private final JLabel end_time;
	private final JTextArea comments;
	private JLabel number_items;
	private final JList my_items_jlist;
	private final List<Item> my_items_list;
	private DefaultListModel my_list_model;
	private final User my_user;
	private List<Integer> item_ids;
	private final Auction my_auction;

	public AuctionGUI(final Auction the_auction,
			final User user) {
		super();
		my_frame = new JFrame(the_auction.getName());
		my_frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
		my_frame.getContentPane()
				.setBackground(Color.WHITE);
		my_frame.setResizable(false);

		my_auction = the_auction;
		NPO_name = new JLabel(the_auction.getNPO());
		date = new JLabel(DF.format(the_auction.getDate()));
		start_time =
				new JLabel(
						doubleToTime(the_auction
								.getStartTime()));
		end_time =
				new JLabel(
						doubleToTime(the_auction
								.getEndTime()));
		comments = new JTextArea(the_auction.getComment());
		comments.setEditable(false);
		my_user = user;
		number_items =
				new JLabel(
						Integer.toString(the_auction
								.getNumberOfItems())
								+ (the_auction
										.getNumberOfItems() > 1 ? " items"
										: " item"));

		my_list_model = new DefaultListModel();
		my_items_list = the_auction.getItems();
		initialize_items_list(my_items_list);
		my_items_jlist = new JList(my_list_model);
		my_items_jlist
				.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		my_items_jlist.setLayoutOrientation(JList.VERTICAL);
		my_items_jlist
				.addMouseListener(new ItemListListener());

		initializeFont();
		on_frame_west();
		on_frame_east();
	}

	protected void initialize_items_list(
			final Collection<Item> the_list) {
		my_list_model.clear();
		List<Item> new_list = new ArrayList<Item>(the_list);
		Collections.sort(new_list);

		item_ids = new ArrayList<Integer>();
		for (Item s : new_list) {
			my_list_model.addElement(s.getID() + " - "
					+ s.getItemName());
			item_ids.add(s.getID());
		}
		number_items.setText(Integer.toString(new_list
				.size())
				+ " item"
				+ (new_list.size() > 1 ? "s" : ""));
	}

	private void initializeFont() {
		NPO_NAME.setFont(STD_FONT.deriveFont(Font.BOLD));
		NPO_name.setFont(STD_FONT);
		DATE.setFont(STD_FONT.deriveFont(Font.BOLD));
		date.setFont(STD_FONT);
		START_TIME.setFont(STD_FONT.deriveFont(Font.BOLD));
		start_time.setFont(STD_FONT);
		END_TIME.setFont(STD_FONT.deriveFont(Font.BOLD));
		end_time.setFont(STD_FONT);
		COMMENTS.setFont(STD_FONT.deriveFont(Font.BOLD));
		comments.setFont(STD_FONT.deriveFont(Font.BOLD));
		number_items
				.setFont(STD_FONT.deriveFont(Font.BOLD));
		my_items_jlist.setFont(STD_FONT);
	}

	private void on_frame_west() {
		JPanel north_north =
				new JPanel(new GridLayout(4, 1));
		JPanel north_south =
				new JPanel(new GridLayout(2, 1));

		north_north.add(NPO_NAME);
		north_north.add(NPO_name);
		north_north.add(DATE);
		north_north.add(date);
		north_north.add(START_TIME);
		north_north.add(start_time);
		north_north.add(END_TIME);
		north_north.add(end_time);

		north_south.add(COMMENTS);
		final JScrollPane scroll_pane =
				new JScrollPane(comments);
		north_south.add(scroll_pane);
		scroll_pane.setPreferredSize(new Dimension(
				CMT_WIDTH, CMT_HEIGHT));
		scroll_pane.setVisible(true);

		final JPanel north = new JPanel(new BorderLayout());
		north.add(north_north, BorderLayout.NORTH);
		north.add(north_south, BorderLayout.SOUTH);
		north_north.setBackground(Color.WHITE);
		north_south.setBackground(Color.WHITE);
		north.setBackground(Color.WHITE);

		my_frame.add(north, BorderLayout.WEST);
	}

	private void on_frame_east() {
		final JPanel south = new JPanel();
		south.setLayout(new BoxLayout(south,
				BoxLayout.PAGE_AXIS));

		if (my_user.getAccessLevel() == 2) {
			JButton add_item = new JButton("Add item");
			add_item.setFont(STD_FONT);
			south.add(add_item);
			add_item.addActionListener(new AddItemListener());
		}

		south.setBackground(Color.WHITE);

		final JScrollPane scroll_items =
				new JScrollPane(my_items_jlist);
		scroll_items.setVisible(true);

		south.add(number_items);
		south.add(scroll_items);

		my_frame.add(south, BorderLayout.EAST);
	}

	public void start(final ProgramStateHandler ps,
			final CalendarModel the_calendar_model,
			final UserAccess ua) {
		final JPanel south =
				new JPanel(new GridLayout(1, 2));
		final JPanel mid = new JPanel();

		if (my_user.getClass() == NPOStaffMember.class) {
			my_frame.addWindowListener(new java.awt.event.WindowAdapter() {
				public void windowClosing(
						java.awt.event.WindowEvent e) {
					ps.write(new File("file.xml"),
							the_calendar_model, ua);
					System.exit(0);
				}
			});
		} else {
			my_frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		}

		my_frame.setVisible(true);
		mid.setBackground(Color.WHITE);
		south.setBackground(Color.WHITE);
		my_frame.setLocationRelativeTo(null);
	}

	/**
	 * Converts a valid time in double to time specified by
	 * TIME_FORMAT.
	 * 
	 * @param the_number A valid time in double.
	 * @return A String according to TIME_FORMAT.
	 */
	private static String doubleToTime(
			final double the_number) {
		final int time_total =
				(int) (the_number * SECONDS_PER_HOUR);
		final Calendar cld = Calendar.getInstance();
		cld.set(Calendar.HOUR_OF_DAY,
				(int) (time_total / SECONDS_PER_HOUR));
		cld.set(Calendar.MINUTE, (int) (time_total
				% SECONDS_PER_HOUR / UNIT_PER_MIN));
		cld.set(Calendar.SECOND,
				(int) (time_total % UNIT_PER_MIN));

		return TF.format(cld.getTime());
	}

	private class ItemListListener implements MouseListener {
		public void
				mouseClicked(final MouseEvent the_event) {

			new ItemGUI(
					AuctionGUI.this.my_auction.getItem((item_ids
							.get(my_items_jlist
									.getSelectedIndex()))),
					AuctionGUI.this.my_user);
		}

		public void
				mouseEntered(final MouseEvent the_event) {
			// do nothing
		}

		public void mouseExited(final MouseEvent the_event) {
			// do nothing
		}

		public void
				mousePressed(final MouseEvent the_event) {
			// do nothing
		}

		public void
				mouseReleased(final MouseEvent the_event) {
			// do nothing
		}
	}

	private class AddItemListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			ItemFormGUI ifg =
					new ItemFormGUI(
							AuctionGUI.this.my_auction,
							AuctionGUI.this);
			ifg.start();
		}
	}
}
